package com.dhcc.DRGsHosp.facade.impl;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.UUID;

import javax.inject.Named;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.openkoala.koala.commons.InvokeResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.dhcc.DRGsHosp.application.DepartmentApplication;
import com.dhcc.DRGsHosp.application.MedicalRecordApplication;
import com.dhcc.DRGsHosp.application.OperInfoApplication;
import com.dhcc.DRGsHosp.application.SystemConfigApplication;
import com.dhcc.DRGsHosp.core.domain.Department;
import com.dhcc.DRGsHosp.core.domain.KPIInfo;
import com.dhcc.DRGsHosp.core.domain.OperInfo;
import com.dhcc.DRGsHosp.facade.OperInfoFacade;
import com.dhcc.DRGsHosp.infra.util.ConstantEnum;
import com.dhcc.DRGsHosp.infra.util.GlobalData;
import com.dhcc.DRGsHosp.infra.util.StringUtils;


/**
 * @title		:OperInfoFacadeImpl.java
 * @description	:
 * @author		:WangTeng
 * @date		:2016年5月20日
 * @version     :1.0
 * @copyright   :DHCC 2013-2016
*/
@Named("drgsHospFacadeImpl34")
public class OperInfoFacadeImpl implements OperInfoFacade{

	@Autowired
	private MedicalRecordApplication medicalRecordApplication;
	
	@Autowired
	private OperInfoApplication operInfoApplication;
	
	@Autowired
	private DepartmentApplication departmentApplication;
	
	@Autowired 
	private SystemConfigApplication systemConfigApplication;
	
	Map<String, String> admIDMap = new HashMap<String, String>();
	List<OperInfo> operInfoList = new LinkedList<OperInfo>();
	
	List<Department> depList = new LinkedList<Department>();
	
	/**
	 * @methodname    :importOperInfoByDate
	 * @description   :抽取手术信息
	 * @param         :
	 * @author        :WangTeng
	 * @return        :
	 * @date          :2016年5月20日
	 */
	@Override
	public InvokeResult importOperInfoByDate(String dateFrom,String dateTo){
		
		BufferedWriter bout = null;
		try {
			bout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(ConstantEnum.DATAPATH+"/operInfo.txt"),"utf-8"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		String operInfo = GlobalData.sysConfig.get("OPER_INFO");
		String wsUrl = "";//导入手术信息地址
		String method = "";//导入手术信息方法
		if(operInfo!=null && operInfo.split("θ").length>1){
			wsUrl = operInfo.split("θ")[0];
			method = operInfo.split("θ")[1];
		}
		JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();
		Client client = clientFactory.createClient(wsUrl);
		HTTPConduit http = (HTTPConduit) client.getConduit();
		http.getClient().setConnectionTimeout(6000000);// 连接超时(毫秒)
		http.getClient().setAllowChunking(false);// 取消块编码
		http.getClient().setReceiveTimeout(6000000);// 响应超时(毫秒)
		
		//获取时间段内首页信息
		System.out.println("================= query medicalrecord information... ==================");
		List<Map<String, Object>> medicalRecords = medicalRecordApplication.findMedicalRecordByOutDate(dateFrom, dateTo);
		
		int mrListSize=medicalRecords.size();
		int times=0;
		int maxNum = 200;
		System.out.println("================= medicalrecord information size : "+mrListSize+"==================");
		System.out.println("================= build operInfo param... ==================");
		while (mrListSize>maxNum) {
			//传入参数
			StringBuilder param = new StringBuilder();
			param.append("<Request>");
			for (int i = 0; i < maxNum; i++) {
				Map<String, Object> medicalrecord = medicalRecords.get(i+times*maxNum);
				admIDMap.put(medicalrecord.get("ADM_ID")+"", medicalrecord.get("ID")+"");
				param.append("<PatAdmInfo><AdmNo>");
				param.append(medicalrecord.get("ADM_ID")+"");
				param.append("</AdmNo></PatAdmInfo>");
			}
			param.append("</Request>");
			
			invokeOperInterface(param, wsUrl, method, http, client, clientFactory, dateFrom, dateTo,bout);
			
			mrListSize-=maxNum;
			times++;
		}
		if (mrListSize>0) {
			StringBuilder param = new StringBuilder();
			param.append("<Request>");
			for (int i = 0; i < mrListSize; i++) {
				Map<String, Object> medicalrecord = medicalRecords.get(i+times*maxNum);
				admIDMap.put(medicalrecord.get("ADM_ID")+"", medicalrecord.get("ID")+"");
				param.append("<PatAdmInfo><AdmNo>");
				param.append(medicalrecord.get("ADM_ID")+"");
				param.append("</AdmNo></PatAdmInfo>");
			}
			param.append("</Request>");
			
			InvokeResult invokeResult = invokeOperInterface(param, wsUrl, method, http, client, clientFactory, dateFrom, dateTo,bout);
			try {
				bout.flush();
				bout.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return invokeResult;
		} else {
			System.out.println("================= no medicalrecord data! ==================");
			return InvokeResult.failure(dateFrom+"-"+dateTo+"没有首页数据");
		}
	}
	
	private InvokeResult invokeOperInterface(StringBuilder param,String wsUrl,String method,HTTPConduit http, Client client, JaxWsDynamicClientFactory clientFactory,String dateFrom,String dateTo,BufferedWriter bout){
		operInfoList = new LinkedList<OperInfo>();
		try {
			try {
				bout.write("-------------------------------------------------------------------------");
			    bout.newLine();
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始导入手术信息（"+dateFrom+"~"+dateTo+"）...");
			    bout.newLine();
			    Object[] response = null;
			    try{
			    	System.out.println("================= invoke operInfo interface begain (method="+method+")... ==================");
			    	response = client.invoke(method, param.toString());
			    	System.out.println("================= invoke operInfo interface complete! ==================");
			    }catch(Exception e){
			    	bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+":"+e.getMessage());
			    	bout.write(param.toString());
			    	e.printStackTrace();
			    	throw new TimeOutException("接口异常");
			    }
				
				String resultXml = "";
				if(response.length>0){
					resultXml = (String) response[0];
				}
				if("-1".equals(resultXml)){
					bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 不存在该病人信息");
			        bout.newLine();
				}
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始解析xml...");
		        bout.newLine();
		        bout.write(resultXml);
		        bout.newLine();
		        System.out.println("================= parse operInfo begain... ==================");
				xmlParse(resultXml);
				System.out.println("================= parse operInfo complete ! ==================");
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 解析完毕，手术信息数量:"+operInfoList.size());
			    bout.newLine();
			    bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始保存手术信息...");
			    bout.newLine();
				if(operInfoList.size()>0){
					try {
						System.out.println("================= operInfo size:"+operInfoList.size()+" ==================");
						System.out.println("================= save operInfo begain... ==================");
						operInfoApplication.updateOperInfo(operInfoList);
						System.out.println("================= save operInfo complete! ==================");
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存成功！");
					    bout.newLine();
					} catch (Exception e) {
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存失败："+e.toString());
				        bout.newLine();
					}
				}else{
					bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 该病人没有手术信息");
			        bout.newLine();
				}
			} catch (Exception e) {
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 解析失败..");
			    bout.newLine();
			    bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 原因:"+e.toString());
			    bout.newLine();
			    bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 重新连接...");
			    bout.newLine();
			    client = clientFactory.createClient(wsUrl);
				http = (HTTPConduit) client.getConduit();
				http.getClient().setConnectionTimeout(6000000);// 连接超时(毫秒)
				http.getClient().setAllowChunking(false);// 取消块编码
				http.getClient().setReceiveTimeout(6000000);// 响应超时(毫秒)
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 重新导入");
			    bout.newLine();
			    try{
			    		Object[] response = client.invoke(method, param.toString());
				        String resultXml = "";
						if(response.length>0){
							resultXml = (String) response[0];
						}
						if("-1".equals(resultXml)){
							bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 不存在该病人手术信息");
					        bout.newLine();
						}
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始解析xml...");
				        bout.newLine();
						xmlParse(resultXml);
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 解析完毕，手术信息数量:"+operInfoList.size());
				        bout.newLine();
				        bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始保存病人医嘱...");
				        bout.newLine();
						if(operInfoList.size()>0){
							try {
								operInfoApplication.updateOperInfo(operInfoList);
								bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存成功2！");
						        bout.newLine();
							} catch (Exception e1) {
								bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存失败2："+e1.getMessage());
						        bout.newLine();
							}
						}else{
							bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 该病人没有手术信息");
					        bout.newLine();
						}
			    }catch(Exception e1){
			    	bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 再次导入失败！"+e1.getMessage());
			        bout.newLine();
			    }
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return InvokeResult.success();
	}

	/**
	 * @methodname    :xmlParse
	 * @description   :SAX解析xml主过程
	 * @param         :
	 * @author        :lileizheng
	 * @return        :null
	 * @date          :2016年1月14日
	 */
	private void xmlParse(String xmlString) throws Exception{
		// step 1: 获得SAX解析器工厂实例
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // step 2: 获得SAX解析器实例
        SAXParser parser = factory.newSAXParser();
        // step 3: 开始进行解析
        StringReader read = new StringReader(xmlString);  
        InputSource source = new InputSource(read);  
        parser.parse(source, new MyHandler());
	}
	
	
	/**
	 * @title		:OrderFacadeImpl.java
	 * @description	:SAX解析xml辅助类
	 * @author		:lileizheng
	 * @date		:2016年1月14日
	 * @version     :1.0
	 * @copyright   :DHCC 2013-2014
	 */
	private class MyHandler extends DefaultHandler
	{
		// 使用栈这个数据结构来保存
	    private Stack<String> stack = new Stack<String>();

	    // 数据
	    private String parId;
		
		private String operCode;
		
		private String operDesc;
		
		private String InfInfo;
		
		private String anesStartDate;
		
		private String anesStartTime;
		
		private String anesEndDate;
		
		private String anesEndTime;
		
		private String operStartDate;
		
		private String operStartTime;
		
		private String operEndDate;
		
		private String operEndTime;
		
		private String enterRoomTime;
		
		private String leaveRoomTime;
		
		private String operRoomId;
		
		private String operRoom;
	    
	    @Override
	    public void startDocument() throws SAXException
	    {
	        System.out.println("start document -> parse begin");
	    }

	    @Override
	    public void endDocument() throws SAXException
	    {

	        System.out.println("end document -> parse finished");
	    }

	    @Override
	    public void startElement(String uri, String localName, String qName,
	            Attributes attributes) throws SAXException
	    {
	        // 将标签名压入栈
	        stack.push(qName);

	    }

	    @Override
	    public void characters(char[] ch, int start, int length)
	            throws SAXException
	    {
	        // 取出标签名
	        String tag = stack.peek();
	        
	        if ("ADMNo".equals(tag))
	        {
	            parId = admIDMap.get(new String(ch, start, length));
	        }
	        else if ("InfInfo".equals(tag))
	        {
	        	InfInfo = new String(ch, start, length);
	        }
	        else if ("OpName".equals(tag))
	        {
	        	operDesc = new String(ch, start, length);
	        }
	        else if ("ANAStartDate".equals(tag))
	        {
	            anesStartDate = new String(ch, start, length);
	        }
	        else if ("ANAStartTime".equals(tag))
	        {
	        	anesStartTime = new String(ch, start, length);
	        }
	        else if ("ANAEndDate".equals(tag))
	        {
	        	anesEndDate = new String(ch, start, length);
	        }
	        else if ("ANAEndTime".equals(tag))
	        {
	            anesEndTime = new String(ch, start, length);
	        }
	        
	        else if ("OpSDate".equals(tag))
	        {
	            operStartDate = new String(ch, start, length);
	        }
	        else if ("OpSTime".equals(tag))
	        {
	        	operStartTime = new String(ch, start, length);
	        }
	        else if ("OpEDate".equals(tag))
	        {
	        	operEndDate = new String(ch, start, length);
	        }
	        else if ("OpETime".equals(tag))
	        {
	            operEndTime = new String(ch, start, length);
	        }
	        
	        else if ("InRoomTime".equals(tag))
	        {
	        	enterRoomTime = new String(ch, start, length);
	        }
	        else if ("LeaveRoomTime".equals(tag))
	        {
	            leaveRoomTime = new String(ch, start, length);
	        }
	        else if ("OPAOpRoomDr".equals(tag))
	        {
	        	operRoomId = new String(ch, start, length);
	        }
	        else if ("OPAOpRoom".equals(tag))
	        {
	        	operRoom = new String(ch, start, length);
	        }
	    }

	    @Override
	    public void endElement(String uri, String localName, String qName)
	            throws SAXException
	    {
	        stack.pop();// 表示该元素解析完毕，需要从栈中弹出标签

	        if ("Oper".equals(qName))
	        {
	            OperInfo operInfo = new OperInfo();
	            
	            operInfo.setParId(parId);
	            operInfo.setOperDesc(operDesc);
	            operInfo.setInfInfo(InfInfo);
	            operInfo.setAnesStartDate(anesStartDate);
	            operInfo.setAnesStartTime(anesStartTime);
	            operInfo.setAnesEndDate(anesEndDate);
	            operInfo.setAnesEndTime(anesEndTime);
	            operInfo.setOperStartDate(operStartDate);
	            operInfo.setOperStartTime(operStartTime);
	            operInfo.setOperEndDate(operEndDate);
	            operInfo.setOperEndTime(operEndTime);
	            operInfo.setEnterRoomTime(enterRoomTime);
	            operInfo.setLeaveRoomTime(leaveRoomTime);
	            operInfo.setOperRoomId(operRoomId);
	            operInfo.setOperRoom(operRoom);
	            operInfoList.add(operInfo);
	        }

	    }
	}
	
	String dateFrom_;
	String dateTo_;
	List<KPIInfo> kpiInfoList = new LinkedList<KPIInfo>();
	@Override
	public InvokeResult importKPIInfoByDate(String dateFrom,String dateTo){
		depList = departmentApplication.findAllDepartment();
		operInfoList = new LinkedList<OperInfo>();
		dateFrom_ = dateFrom;
		dateTo_ = dateTo;
		
		String depBedDays =  GlobalData.sysConfig.get("DEP_BED_DAYS");
		String wsUrl = "";//导入床日信息地址
		String method = "";//导入床日信息方法
		if(depBedDays!=null && depBedDays.split("θ").length>1){
			wsUrl = depBedDays.split("θ")[0];
			method = depBedDays.split("θ")[1];	
		}
		BufferedWriter bout = null;
		JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();
		Client client = clientFactory.createClient(wsUrl);
		HTTPConduit http = (HTTPConduit) client.getConduit();
		http.getClient().setConnectionTimeout(6000000);// 连接超时(毫秒)
		http.getClient().setAllowChunking(false);// 取消块编码
		http.getClient().setReceiveTimeout(6000000);// 响应超时(毫秒)
		
		try {
			bout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(ConstantEnum.DATAPATH+"/KPIInfo.txt"),"utf-8"));

			try {
				bout.write("-------------------------------------------------------------------------");
			    bout.newLine();
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始导入KPI信息（"+dateFrom+"~"+dateTo+"）...");
			    bout.newLine();
			    Object[] response = null;
			    try{
			    	response = client.invoke(method, dateFrom, dateTo);
			    }catch(Exception e){
			    	bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+":"+e.getMessage());
			    	e.printStackTrace();
			    	throw new TimeOutException("接口异常");
			    }
				
				String resultXml = "";
				if(response.length>0){
					resultXml = (String) response[0];
				}
				if("-1".equals(resultXml)){
					bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 不存在该病人信息");
			        bout.newLine();
				}
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始解析xml...");
		        bout.newLine();
				xmlParseKPI(resultXml);
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 解析完毕，KPI信息数量:"+kpiInfoList.size());
			    bout.newLine();
			    bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始保存病人医嘱...");
			    bout.newLine();
				if(kpiInfoList.size()>0){
					try {
						operInfoApplication.saveOrUpdate(kpiInfoList);
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存成功！");
					    bout.newLine();
					} catch (Exception e) {
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存失败："+e.toString());
				        bout.newLine();
					}
				}else{
					bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 没有KPI信息");
			        bout.newLine();
				}
			} catch (Exception e) {
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 解析失败..");
			    bout.newLine();
			    bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 原因:"+e.toString());
			    bout.newLine();
			    bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 重新连接...");
			    bout.newLine();
			    client = clientFactory.createClient(wsUrl);
				http = (HTTPConduit) client.getConduit();
				http.getClient().setConnectionTimeout(6000000);// 连接超时(毫秒)
				http.getClient().setAllowChunking(false);// 取消块编码
				http.getClient().setReceiveTimeout(6000000);// 响应超时(毫秒)
				bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 重新导入");
			    bout.newLine();
			    try{
			    		Object[] response = client.invoke(method, dateFrom, dateTo);
				        String resultXml = "";
						if(response.length>0){
							resultXml = (String) response[0];
						}
						if("-1".equals(resultXml)){
							bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 不存在KPI信息");
					        bout.newLine();
						}
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始解析xml...");
				        bout.newLine();
						xmlParseKPI(resultXml);
						bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 解析完毕，KPI信息数量:"+kpiInfoList.size());
				        bout.newLine();
				        bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 开始保存...");
				        bout.newLine();
						if(kpiInfoList.size()>0){
							try {
								operInfoApplication.saveOrUpdate(kpiInfoList);
								bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存成功2！");
						        bout.newLine();
							} catch (Exception e1) {
								bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 保存失败2："+e1.getMessage());
						        bout.newLine();
							}
						}else{
							bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 该病人没有KPI");
					        bout.newLine();
						}
			    }catch(Exception e1){
			    	bout.write("at "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 再次导入失败！"+e1.getMessage());
			        bout.newLine();
			    }
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				bout.flush();
				bout.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return InvokeResult.success();
	}

	/**
	 * @methodname    :xmlParse
	 * @description   :SAX解析xml主过程
	 * @param         :
	 * @author        :lileizheng
	 * @return        :null
	 * @date          :2016年1月14日
	 */
	private void xmlParseKPI(String xmlString) throws Exception{
		// step 1: 获得SAX解析器工厂实例
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // step 2: 获得SAX解析器实例
        SAXParser parser = factory.newSAXParser();
        // step 3: 开始进行解析
        StringReader read = new StringReader(xmlString);  
        InputSource source = new InputSource(read);  
        parser.parse(source, new MyHandlerKPI());
	}
	
	
	/**
	 * @title		:OrderFacadeImpl.java
	 * @description	:SAX解析xml辅助类
	 * @author		:lileizheng
	 * @date		:2016年1月14日
	 * @version     :1.0
	 * @copyright   :DHCC 2013-2014
	 */
	private class MyHandlerKPI extends DefaultHandler
	{
		// 使用栈这个数据结构来保存
	    private Stack<String> stack = new Stack<String>();
	    
	    Map<String, String> wardDepNameMap = new HashMap<String, String>();//病区科室名称对照信息
	    Map<String, String> depCodeMap = new HashMap<String, String>();
	    List<Map<String, String>> dataList = new ArrayList<Map<String,String>>();
	    
	    // 数据
	    private String depCode;
		
		private String depDesc;
		
		private String kpiCode;
		
		private String kpiDesc;
		
		private String kpiValue;
		
	    
	    @Override
	    public void startDocument() throws SAXException
	    {
	        System.out.println("start document -> parse begin");
	        //所有科室
			List<Department> depList = departmentApplication.findAllDepartment();
			Map<String, String> tempMap = new HashMap<String, String>();
			for (Department dep : depList) {
				tempMap.put(dep.getDepName(), dep.getDepWard());
				depCodeMap.put(dep.getDepName(), dep.getDepCode());
			}
			
			for (String depName : tempMap.keySet()) {
				if (!StringUtils.isEmpty(tempMap.get(depName))) {
					String[] wards = tempMap.get(depName).split(",");
					for (String ward : wards) {
						wardDepNameMap.put(ward, depName);
					}
				}
			}
	    }

	    @Override
	    public void endDocument() throws SAXException
	    {

	        System.out.println("end document -> parse finished");
	        
	        //根据id排序dataList
	        Collections.sort(dataList, new Comparator<Map<String, String>>() {
				@Override
				public int compare(Map<String, String> o1,Map<String, String> o2) {
					return o1.get("id").compareTo(o2.get("id"));
				}
			});
	        
	        for (int i = 0; i < dataList.size(); i++) {
	        	Map<String, String> map = dataList.get(i);
				for (int j = 0; j < dataList.size(); j++) {
					if (j>i) {//不和自身比较
						if (map.get("id").equals(dataList.get(j).get("id"))) {
							map.put("kpiValue", (toDouble(map.get("kpiValue")) + toDouble(dataList.get(j).get("kpiValue"))) + "");
						} else {
							KPIInfo kpiInfo = new KPIInfo();
				            kpiInfo.setId(UUID.randomUUID().toString());
				            kpiInfo.setDepCode(map.get("depCode"));
				            kpiInfo.setDepDesc(map.get("depDesc"));
				            kpiInfo.setKpiCode(map.get("kpiCode"));
				            kpiInfo.setKpiDesc(map.get("kpiDesc"));
				            kpiInfo.setKpiValue(map.get("kpiValue"));
				            kpiInfo.setDateFrom(map.get("dateFrom"));
				            kpiInfo.setDateTo(map.get("dateTo"));
				            
				            kpiInfoList.add(kpiInfo);
				            
				            i=(j-1);//下次外层循环从j开始，for循环里有i++,所以i=j-1
							break;  //跳出内层循环
						}
					}
				}
			}
	    }

	    @Override
	    public void startElement(String uri, String localName, String qName,
	            Attributes attributes) throws SAXException
	    {
	        // 将标签名压入栈
	        stack.push(qName);

	    }

	    @Override
	    public void characters(char[] ch, int start, int length)
	            throws SAXException
	    {
	        // 取出标签名
	        String tag = stack.peek();

	        if ("DepCode".equals(tag))
	        {
	        	depCode = new String(ch, start, length);
	        }
	        else if ("DepDesc".equals(tag))
	        {
	        	depDesc = wardDepNameMap.get(new String(ch, start, length));
	        	depCode = depCodeMap.get(depDesc);
//	        	for (Department dep : depList) {
//	        		if (new String(ch, start, length).equals(dep.getDepName())) {
//	        			depDesc = dep.getDepName();
//						depCode = dep.getDepCode();
//	        		} else if (new String(ch, start, length).equals(dep.getDepHis())) {
//						depDesc = dep.getDepName();
//						depCode = dep.getDepCode();
//					}
//				}
	        }
	        else if ("KPICode".equals(tag))
	        {
	            kpiCode = new String(ch, start, length);
	        }
	        else if ("KPIDesc".equals(tag))
	        {
	        	kpiDesc = new String(ch, start, length);
	        }
	        else if ("KPIValue".equals(tag))
	        {
	        	kpiValue = new String(ch, start, length);
	        }
	    }

	    @Override
	    public void endElement(String uri, String localName, String qName)
	            throws SAXException
	    {
	        stack.pop();// 表示该元素解析完毕，需要从栈中弹出标签

	        if ("KPI".equals(qName))
	        {
	        	Map<String, String> map = new HashMap<String, String>();
	        	map.put("id", depCode+"|"+kpiCode);//depCode+kpiCode确定同一kpi
	        	map.put("depCode", depCode);
	        	map.put("depDesc", depDesc);
	        	map.put("kpiCode", kpiCode);
	        	map.put("kpiDesc", kpiDesc);
	        	map.put("kpiValue", kpiValue);
	        	map.put("dateFrom", dateFrom_);
	        	map.put("dateTo", dateTo_);
	        	dataList.add(map);
	        }

	    }
	    
	    private double toDouble(Object object){
	    	
	    	if (object==null || "".equals((object+"").trim())) {
				return 0;
			} else {
				return Double.valueOf(object+"");
			}
	    }
	}
	
	class TimeOutException extends Exception{
		private static final long serialVersionUID = 1L;

		public TimeOutException(String msg)  
	    {  
	        super(msg);  
	    } 
	}
	
	/**
	 * @methodname    :importKPIInfoByDate
	 * @description   :导入上月科室床日信息
	 * @param         :
	 * @author        :WangTeng
	 * @return        :
	 * @date          :2016年6月7日
	 */
	@Override
	public void importKPIInfoByLastMonth() {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
    	Calendar calendar=Calendar.getInstance();
    	calendar.add(Calendar.MONTH, -1);//计算上个月
		calendar.set(Calendar.DAY_OF_MONTH,calendar.getActualMinimum(Calendar.DAY_OF_MONTH));//月第一天 
		String dateFrom=sdf.format(calendar.getTime());
		
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));//月最后一天 
		String dateTo=sdf.format(calendar.getTime());
		
		System.out.println("["+sdf.format(new Date())+"]import KPI information by interface...");
		importKPIInfoByDate(dateFrom, dateTo);
	}
}
